
// 性能压力测试
// 可控制写日志的线程数量
// 可控制日志数据的总大小
// 同步，异步日志器各自的性能测试

#include "../logs/log.h"
#include <chrono>

// 传入日志器名称，线程数量，日志个数，单条日志大小
void bench(const std::string& logger_name, size_t thread_num, size_t log_num, size_t single_log_size)
{
    cout << "日志器名称：" << logger_name << "  线程数量：" << thread_num << endl;
    cout << "日志个数：" << log_num << "  单条日志大小：" << single_log_size  << "byte" << endl;
    cout << "日志总大小：" << log_num * single_log_size / 1024 / 1024 << "Mb" << endl;

    // 获取日志器
    log::logger::ptr logger = log::get_logger(logger_name);

    // 组织指定大小的日志消息
    std::string msg(single_log_size - 1, 'x');

    std::vector<std::thread> thread_vec;
    std::vector<double> cost_vec(thread_num);//每个线程所花费的时间
    size_t msg_num = log_num / thread_num;//每个线程需要处理的日志个数
    for(size_t i = 0; i < thread_num; ++i)
    {
        thread_vec.emplace_back([&, i]()
        {
            // https://zh.cppreference.com/w/cpp/chrono/high_resolution_clock/now
            auto start = std::chrono::high_resolution_clock::now();
            for(size_t j = 0; j < msg_num; ++j)
            {
                logger->fatal("%s", msg.c_str());
            }
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;
            cost_vec[i] = cost.count();
            cout << "线程" << i << "：" << "日志写入个数：" << msg_num << "  " << "耗时：" << cost.count() << "s" << endl; 
        });
    }

    for(size_t i = 0; i < thread_num; ++i)
    {
        thread_vec[i].join();
    }

    // 多线程总耗时为线程中最高的那一个的耗时
    double max_cost = cost_vec[0];
    for(size_t i = 0; i < cost_vec.size(); ++i)
    {
        if(max_cost < cost_vec[i])
            max_cost = cost_vec[i];
    }

    // 平均每秒输出多少大小的日志
    size_t log_size_per_sec = log_num * single_log_size / max_cost / 1024 / 1024;
    // 平均每秒输出多个日志
    size_t log_num_per_sec = log_num / max_cost;
    cout << "平均每秒输出日志" << log_size_per_sec << "Mb" << endl;
    cout << "平均每秒输出日志" << log_num_per_sec << "个" << endl;
    cout << "总耗时：" << max_cost << "s" << endl;
}

// 同步日志性能压力测试
void sync_bench()
{
    std::unique_ptr<log::build_logger> b(new log::global_build_logger());
    b->build_logger_name("sync_bench");
    b->build_formatter("%m%N");
    b->build_logger_type(log::logger_type::LOGGER_SYNC);
    b->build_sink<log::file_sink>("./logfile/file_sink.log");
    b->build();

    // 本次测试所用机器是华为的一个云服务器
    bench("sync_bench", 1, 1000000, 100);//总耗时：1.62604s
    bench("sync_bench", 4, 1000000, 100);//总耗时：1.69261s
    // 同步日志器多线程总耗时要比单线程慢
    // 磁盘性能达到上限，单线程不存在锁冲突，故更快
}

// 异步日志性能压力测试
void async_bench()
{
    std::unique_ptr<log::build_logger> b(new log::global_build_logger());
    b->build_logger_name("async_bench");
    b->build_formatter("%m%N");
    b->build_logger_type(log::logger_type::LOGGER_ASYNC);
    b->build_enable_async_unsafe();//极限性能测试
    b->build_sink<log::file_sink>("./logfile/file_sink.log");
    b->build();
    
    // 本次测试所用机器是华为的一个云服务器
    // 注意传入的日志器名称
    bench("async_bench", 1, 1000000, 100);//总耗时：1.63295s
    bench("async_bench", 4, 1000000, 100);//总耗时：1.57751s
    // 同步日志器多线程总耗时要比单线程快
    // 多个线程同时向内存写入数据，更多考虑cpu和内存的性能，效率提升
}

int main()
{
    //sync_bench();
    async_bench();
    return 0;
}